import axios from "axios";
import dayjs from "dayjs";
import qs from "query-string";

/**
 * Check if an element has a class
 * @param {HTMLElement} ele
 * @param {string} cls
 * @returns {boolean}
 */
export function hasClass(ele: HTMLElement, cls: string) {
  return !!ele.className.match(new RegExp("(\\s|^)" + cls + "(\\s|$)"));
}

/**
 * Add class to element
 * @param {HTMLElement} ele
 * @param {string} cls
 */
export function addClass(ele: HTMLElement, cls: string) {
  if (!hasClass(ele, cls)) ele.className += " " + cls;
}

/**
 * Remove class from element
 * @param {HTMLElement} ele
 * @param {string} cls
 */
export function removeClass(ele: HTMLElement, cls: string) {
  if (hasClass(ele, cls)) {
    const reg = new RegExp("(\\s|^)" + cls + "(\\s|$)");
    ele.className = ele.className.replace(reg, " ");
  }
}

/**
 * 判断是否是外部链接
 *
 * @param {string} path
 * @returns {Boolean}
 */
export function isExternal(path: string) {
  const isExternal = /^(https?:|http?:|mailto:|tel:)/.test(path);
  return isExternal;
}

/**
 * 格式化增长率，保留两位小数 ，并且去掉末尾的0  取绝对值
 *
 * @param growthRate
 * @returns
 */
export function formatGrowthRate(growthRate: number) {
  if (growthRate === 0) {
    return "-";
  }

  const formattedRate = Math.abs(growthRate * 100)
    .toFixed(2)
    .replace(/\.?0+$/, "");
  return formattedRate + "%";
}

// 时间戳转日期
export function formatTimestamp(time: string) {
  // 将秒级时间戳转换为毫秒级
  const date = new Date(time);

  // 获取年、月、日、小时、分钟
  const year = date.getFullYear();
  const month = date.getMonth() + 1; // 月份从0开始，所以要加1
  const day = date.getDate();
  const hours = date.getHours();
  const minutes = date.getMinutes();

  // 格式化日期字符串
  const formattedDate = `${year}年${month}月${day}日 ${hours}:${minutes.toString().padStart(2, "0")}`;

  return formattedDate;
}

/**
 * 下载：文件名首选前端设置、然后是后端接口设置、最后是默认使用日期作为文件名
 *
 * @param url URL
 * @param params 查询条件
 * @param fileName 文件名
 */
export function download(url: string, params: any, fileName: string | undefined) {
  return axios
    .get(url, {
      params,
      paramsSerializer: (obj) => {
        return qs.stringify(obj);
      },
      responseType: "blob",
    })
    .then(async (res) => {
      // 获取文件名:当调用此方法导出，但没有设置文件名时，去获取后端设置的文件名
      if (!fileName) {
        const contentDisposition = res.headers["content-disposition"];
        const pattern = new RegExp("filename=([^;]+\\.[^\\.;]+);*");

        // exec()的返回值是一个数组，第一个元素是整个匹配项，从第二个开始才是匹配项
        const result = pattern.exec(contentDisposition) || "";
        // 对名字进行解码
        fileName = window.decodeURI(result[1]);

        // 如果解析发现后端没传文件名，则使用日期作为默认文件名
        if (!fileName) {
          fileName = `${fileName}_${dayjs().format("YYYYMMDDHHmmss")}`;
        }
      }

      // 创建下载的链接
      const blob = new Blob([res.data], {
        type: "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet;charset=utf-8",
      });
      const downloadElement = document.createElement("a");
      const href = window.URL.createObjectURL(blob);
      downloadElement.style.display = "none";
      downloadElement.href = href;
      // 下载后文件名
      downloadElement.download = `${fileName}`;
      document.body.appendChild(downloadElement);
      // 点击下载
      downloadElement.click();
      // 下载完成，移除元素
      document.body.removeChild(downloadElement);
      // 释放掉 blob 对象
      window.URL.revokeObjectURL(href);
    })
    .catch((error: any) => {
      console.log(error);
    });
}

/**
 * 千分位
 *
 * @param num 数据
 */
export function formatThousand(num: number) {
  if (isNaN(num)) {
    throw new TypeError("num is not a number");
  }

  var groups = /([-+]?)(\d*)(\.\d+)?/g.exec("" + num) || [];
  var mask = groups[1]; // 符号位
  var integers = (groups[2] || "").split(""); // 整数部分
  var decimal = groups[3] || ""; // 小数部分
  var remain = integers.length % 3;

  var temp = integers
    .reduce(function (previousValue, currentValue, index) {
      if (index + 1 === remain || (index + 1 - remain) % 3 === 0) {
        return previousValue + currentValue + ",";
      } else {
        return previousValue + currentValue;
      }
    }, "")
    .replace(/,$/g, "");
  return mask + temp + decimal;
}

/**
 * 日期格式化工具函数
 * @param time 时间戳（number）或 UTC 格式时间字符串（string）
 * @param format 格式化字符串，例如 "Y-M-D h:m:s"
 * @returns 格式化后的日期字符串
 * 使用：formatDate(timestamp, 'Y-M-D h:m:s')、formatDate(utcTime, 'Y/M/D h:m:s')、formatDate(timestamp, 'Y年M月D日 h时m分s秒')
 */
export function formatDate(time: number | string, format: string): string {
  // 将时间转换为 Date 对象
  const date = new Date(time);

  // 如果传入的时间无效，抛出错误
  if (isNaN(date.getTime())) {
    throw new Error("Invalid time value");
  }

  // 定义格式化规则
  const formatRules: Record<string, string> = {
    Y: String(date.getFullYear()), // 年份
    M: String(date.getMonth() + 1).padStart(2, "0"), // 月份（补零）
    D: String(date.getDate()).padStart(2, "0"), // 日期（补零）
    h: String(date.getHours()).padStart(2, "0"), // 小时（补零）
    m: String(date.getMinutes()).padStart(2, "0"), // 分钟（补零）
    s: String(date.getSeconds()).padStart(2, "0"), // 秒（补零）
  };

  // 替换格式化字符串中的占位符
  let formattedDate = format;
  for (const key in formatRules) {
    if (Object.prototype.hasOwnProperty.call(formatRules, key)) {
      formattedDate = formattedDate.replace(new RegExp(key, "g"), formatRules[key]);
    }
  }

  return formattedDate;
}
